﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using Landscape.Business.Entities;
using NHibernate.Criterion;

namespace Landscape.Business.FNH.Activities
{
    public class AdminActivities : BusinessActivities
    {
        public AdminActivities()
            : base()
        { }

        public AdminActivities(ISession pSession)
            : base(pSession)
        { }

        public IList<SystemModule> GetAllInternalSystemModules()
        {
            var criteria = CurrentSession.CreateCriteria<SystemModule>();
            criteria.Add(Expression.Eq("IsDisabled", false));
            criteria.Add(Expression.Eq("IsDeleted", false));
            criteria.Add(Expression.Eq("Location", "INTERNAL"));
            criteria.AddOrder(new Order("IndexNumber", true));

            return criteria.List<SystemModule>();
        }

        public IList<SystemModule> GetAllExternalSystemModules()
        {
            var criteria = CurrentSession.CreateCriteria<SystemModule>();
            criteria.Add(Expression.Eq("IsDisabled", false));
            criteria.Add(Expression.Eq("IsDeleted", false));
            criteria.Add(Expression.Eq("Location", "EXTERNAL"));
            criteria.AddOrder(new Order("IndexNumber", true));

            return criteria.List<SystemModule>();
        }

        public SystemModulePrivilege GetPrivilegeByID(Guid pID)
        {
            return CurrentSession.Get<SystemModulePrivilege>(pID);
        }

        public SystemResourceMap GetSystemResourceByID(Guid pResID)
        {
            return CurrentSession.Get<SystemResourceMap>(pResID);
        }

        #region Role related methos

        public Role GetRoleByID(Guid pID)
        {
            return CurrentSession.Load<Role>(pID);
        }

        public Role GetRoleByName(string pName)
        {
            var criteria = CurrentSession.CreateCriteria<Role>();
            criteria.Add(Expression.Eq("Name", pName));

            return ((criteria.List<Role>().Count > 0) ? criteria.List<Role>().Single() : null);
        }

        public bool HasRoleExists(Guid pID)
        {
            var criteria = CurrentSession.CreateCriteria<Role>();
            criteria.Add(Expression.Eq("ID", pID));

            return criteria.List().Count > 0;
        }

        public Guid SaveRole(Role pRoleObject)
        {
            CurrentSession.SaveOrUpdate(pRoleObject);
            return this.GetRoleByName(pRoleObject.Name).ID;
        }

        public void DeleteRole(Role pRoleObject)
        {
            //string newDelName = "_" + pRoleObject.ID + "_D";

            //In future it might need to check the whole lenght of the string plus the delete name is more than 254 or not

            pRoleObject.Name = "_" + pRoleObject.ID + "_D";
            pRoleObject.IsDeleted = true;

            this.SaveRole(pRoleObject);
        }

        public IList<Role> GetAllRoles()
        {
            var criteria = CurrentSession.CreateCriteria<Role>();
            criteria.Add(Expression.Eq("IsDeleted", false));
            criteria.AddOrder(new Order("UpdatedDate", false));

            return criteria.List<Role>();
        }

        public int GetRoleCount()
        {
            var criteria = CurrentSession.CreateCriteria<Role>();
            criteria.Add(Expression.Eq("IsDeleted", false));
            criteria.AddOrder(new Order("UpdatedDate", false));

            return criteria.List().Count;
        }

        public IList<Role> GetAllRoles(int pPageNo, int pPageSize)
        {
            var criteria = CurrentSession.CreateCriteria<Role>();
            criteria.Add(Expression.Eq("IsDeleted", false));
            criteria.AddOrder(new Order("UpdatedDate", false));

            return criteria.List<Role>().Skip(pPageNo * pPageSize).Take(pPageSize).ToList();
        }

        public bool CheckDuplicateRole(string pRoleName)
        {
            var criteria = CurrentSession.CreateCriteria<Role>();
            criteria.Add(Expression.InsensitiveLike("Name", pRoleName));

            return criteria.List().Count > 0;
        }

        #endregion

        #region User related methods

        /// <summary>
        /// This method saves teh user identity, user master, user roles and user data restriction
        /// </summary>
        /// <param name="pUserIdentity">UserIdentity object</param>
        /// <returns>The primary key of user identity</returns>
        public Guid SaveUser(UserMaster pUserIdentity)
        {
            CurrentSession.SaveOrUpdate(pUserIdentity);
            return this.GetUserMasterByLoginName(pUserIdentity.Identity.LoginName).ID;
        }

        private UserMaster GetUserMasterByLoginName(string pLoginName)
        {
            var criteria = CurrentSession.CreateCriteria<UserMaster>();           

            return criteria.List<UserMaster>().Where(exp=>exp.Identity.LoginName == pLoginName).SingleOrDefault();
        }

        private UserIdentity GetUserIdentityByName(string pLoginName)
        {
            var criteria = CurrentSession.CreateCriteria<UserIdentity>();
            criteria.Add(Expression.Eq("LoginName", pLoginName));

            return criteria.List<UserIdentity>().Single();
        }

        public UserIdentity GetUserIdentityByID(Guid pID)
        {
            return CurrentSession.Get<UserIdentity>(pID);
        }

        public UserMaster GetUserMasterByID(Guid pID)
        {
            return CurrentSession.Get<UserMaster>(pID);
        }

        public UserMaster GetUserMasterByCredentials(string pUserName, bool pForLogin)
        {
            var criteria = CurrentSession.CreateCriteria<UserIdentity>();
            criteria.Add(Expression.InsensitiveLike("LoginName", pUserName));

            var userIdentity = criteria.UniqueResult<UserIdentity>();

            criteria = CurrentSession.CreateCriteria<UserMaster>();
            criteria.Add(Expression.Eq("Identity", userIdentity));
            if (pForLogin)
                criteria.Add(Expression.Eq("IsDeleted", false));

            return criteria.UniqueResult<UserMaster>();
        }

        public IList<UserMaster> GetAllUsers(int pPageNo, int pPageSize)
        {
            var criteria = CurrentSession.CreateCriteria<UserMaster>();
            criteria.Add(Expression.Eq("IsDeleted", false));
            criteria.AddOrder(new Order("UpdatedDate", false));

            return (pPageSize == -1 ? criteria.List<UserMaster>() : criteria.List<UserMaster>().Skip(pPageNo * pPageSize).Take(pPageSize).ToList());
        }

        public int GetUsersCount()
        {
            var criteria = CurrentSession.CreateCriteria<UserMaster>();
            criteria.Add(Expression.Eq("IsDeleted", false));
            criteria.AddOrder(new Order("UpdatedDate", false));

            return criteria.List().Count;
        }

        public IList<Role> GetUserRoles(Guid pUserID, int pPageNo, int pPageSize)
        {
            var userMaster = CurrentSession.Get<UserMaster>(pUserID);
            if (userMaster.IsSystemAdmin)
            {
                return GetAllRoles(pPageNo, pPageSize);
            }
            else
            {
                return userMaster.Resources.Select(exp=>exp.Role).Distinct(new EqualityComparers.RoleComparer()).ToList();
            }
        }

        public int GetUserRoleCount(Guid pUserID)
        {
            var userMaster = CurrentSession.Get<UserMaster>(pUserID);
            if (userMaster.IsSystemAdmin)
            {
                return GetRoleCount();
            }
            else
            {
                return userMaster.Resources.Select(exp => exp.Role).Distinct(new EqualityComparers.RoleComparer()).Count();
            }
        }

        public IList<SystemModule> GetSystemAdminModules(string pRegion)
        {
            var criteria = CurrentSession.CreateCriteria<SystemModule>();
            criteria.Add(Expression.Eq("IsDeleted", false));
            criteria.Add(Expression.Eq("IsDisabled", false));
            criteria.Add(Expression.Eq("Location", pRegion));

            return criteria.List<SystemModule>();
        }

        public IList<SystemModule> GetUserModules(Guid pUserCode, string pRegion)
        {
            List<SystemModule> modules = new List<SystemModule>();

            Func<SystemModule, List<Department>, List<SystemModule>> FuncGetParents = null;
            FuncGetParents = (sm, uDepts) =>
            {
                List<SystemModule> smodules = new List<SystemModule>();
                if (sm.ParentModule.HasValue)
                {
                    var parent = this.GetSystemModuleByCode(sm.ParentModule.Value);
                    if (!smodules.Contains(parent))
                    {
                        if (uDepts.Count == 0 || (uDepts.Intersect(parent.Departments, new EqualityComparers.DepartmentComparer()).Count() > 0))
                        {
                            smodules.Add(parent);
                            smodules.AddRange(FuncGetParents(parent, uDepts));
                        }
                    }
                }
                return smodules;
            };

            var uDet = this.GetUserMasterByID(pUserCode);
            if (uDet.Resources != null && uDet.Resources.Select(exp => exp.Role).Count() > 0)
            {
                var uDepts = uDet.Resources.Select(exp => exp.Department).Distinct(new EqualityComparers.DepartmentComparer());
                var allPrivileges = uDet.Resources.Select(exp => exp.Role).Select(exp => exp.Privileges).Aggregate((allPrivs, next) => { next.AsParallel().ForAll((p) => allPrivs.Add(p)); return allPrivs; });
                allPrivileges.AsParallel().ForAll((p) =>
                {
                    if (!modules.Contains(p.Module) && (uDepts.Count() == 0 || uDepts.Intersect(p.Module.Departments, new EqualityComparers.DepartmentComparer()).Count() > 0))
                    {
                        modules.Add(p.Module); modules.AddRange(FuncGetParents(p.Module, uDepts.ToList()));
                    }
                });
            }

            return modules.Distinct().ToList();
        }

        public SystemModule GetSystemModuleByCode(Guid pSMID)
        {
            using (var nhSession = NHSessionManager.GetManager().GetSession())
            {
                var sm = nhSession.Get<SystemModule>(pSMID);
                NHibernateUtil.Initialize(sm.Departments);
                return sm;
            }
        }

        public List<SystemModulePrivilege> GetUserPrivilegesFor(Guid pPageID, Guid pUserID)
        {
            List<SystemModulePrivilege> privileges = new List<SystemModulePrivilege>();

            var uMaster = CurrentSession.Get<UserMaster>(pUserID);
            var sysModule = CurrentSession.Get<SystemModule>(pPageID);

            if (!uMaster.IsSystemAdmin)
            {
                foreach (var role in uMaster.Resources.Select(exp => exp.Role))
                {
                    if (role.Privileges != null && role.Privileges.Count > 0 && sysModule != null)
                    {
                        //Check if role privileges and system module privileges has any thing in common
                        var privs = role.Privileges.Intersect(sysModule.Privileges);
                        if (privs != null)
                        {
                            privileges.AddRange(role.Privileges.Intersect(sysModule.Privileges));
                        }
                    }
                }
            }
            else
            {
                if (sysModule != null)
                    privileges.AddRange(sysModule.Privileges);
            }

            return privileges;
        }

        public List<Vessel> GetUserVessels(Guid pUserID)
        {
            List<Vessel> userVessles = new List<Vessel>();

            var uMaster = CurrentSession.Get<UserMaster>(pUserID);
            if (!uMaster.IsSystemAdmin)
            {
                userVessles.AddRange(uMaster.Resources.Select(exp => exp.Vessel));
            }
            else
            {
                var criteria = CurrentSession.CreateCriteria<Vessel>();
                criteria.Add(Expression.Eq("IsDeleted", false));
                criteria.Add(Expression.Eq("IsDisabled", false));

                userVessles.AddRange(criteria.List<Vessel>());
            }

            return userVessles;
        }

        public List<ModulePrivilegeCodes> GetUserPrivilegesForModule(Guid pModuleID, Guid pUserCode)
        {
            List<ModulePrivilegeCodes> privileges = new List<ModulePrivilegeCodes>();

            var uDet = CurrentSession.Get<UserMaster>(pUserCode);
            if (uDet.Resources != null && uDet.Resources.Select(exp => exp.Role).Count() > 0)
            {
                foreach (var r in uDet.Resources.Select(exp => exp.Role))
                {
                    privileges.AddRange(r.Privileges.Where(exp => exp.Module.ID == pModuleID).Select(exp => exp.PrivilegeCode));
                }                
            }

            return privileges;
        }

        public IEnumerable<Department> GetAllDepartments()
        {
            var criteria = CurrentSession.CreateCriteria<Department>();
            criteria.Add(Expression.Eq("IsDeleted", false));

            return criteria.List<Department>();
        }

        public Department GetDepartmentByID(Guid pDeptID)
        {
            return CurrentSession.Get<Department>(pDeptID);
        }

        public IEnumerable<Department> GetUserDepartments(Guid pUserCode)
        {
            var uMaster = this.GetUserMasterByID(pUserCode);

            if (uMaster.IsSystemAdmin)
            {
                var criteria = CurrentSession.CreateCriteria<Department>();
                criteria.Add(Expression.Eq("IsDeleted", false));

                return criteria.List<Department>();
            }
            else
            {
                return uMaster.Resources.Select(exp => exp.Department);
            }
        }

        #endregion

        #region Item related methods

        public Guid SaveItem(MachineType itemBizObject)
        {
            CurrentSession.SaveOrUpdate(itemBizObject);

            var criteria = CurrentSession.CreateCriteria<MachineType>();
            criteria.Add(Expression.Eq("Name", itemBizObject.Name));
            criteria.Add(Expression.Eq("Category", itemBizObject.Category));

            if (itemBizObject.Parent != null)
                criteria.Add(Expression.Eq("Parent", itemBizObject.Parent));

            return criteria.UniqueResult<MachineType>().ID;
        }

        public IList<MachineType> GetItemsByType(MachineCategory itemType, int pPageNo, int pPageSize)
        {
            var criteria = CurrentSession.CreateCriteria<MachineType>();
            criteria.Add(Expression.Eq("IsDeleted", false));
            criteria.Add(Expression.Eq("Category", itemType));
            criteria.AddOrder(new Order("Name", true));

            if (pPageNo != -1)
                return criteria.List<MachineType>().Skip(pPageNo * pPageSize).Take(pPageSize).ToList();
            else
                return criteria.List<MachineType>();
        }

        public int GetItemsByTypeCount(MachineType itemType)
        {
            var criteria = CurrentSession.CreateCriteria<MachineType>();
            criteria.Add(Expression.Eq("IsDeleted", false));
            criteria.Add(Expression.Eq("Type", itemType));

            return criteria.List<MachineType>().Count;
        }

        public MachineType GetItemByID(Guid pID)
        {
            return CurrentSession.Get<MachineType>(pID);
        }

        public IList<MachineType> GetItemsBy(string pName, string pItemType, int pPageNo, int pPageSize)
        {
            var criteria = CurrentSession.CreateCriteria<MachineType>();
            criteria.CreateAlias("Synonyms", "SYN", NHibernate.SqlCommand.JoinType.LeftOuterJoin);
            criteria.Add(Expression.Eq("IsDeleted", false));
            
            if (pItemType != null && pItemType.Trim() != string.Empty)
                criteria.Add(Expression.Eq("Type", (MachineType)Enum.Parse(typeof(MachineType), pItemType)));

            if (pName != null && pName.Trim() != string.Empty)
            {
                pName = string.Format("%{0}%", pName);
                criteria.Add(Expression.Or(Expression.InsensitiveLike("Name", pName), Expression.InsensitiveLike("SYN.Name", pName)));        
            }

            criteria.AddOrder(new Order("Name", true));            

            if (pPageNo != -1)
                return criteria.List<MachineType>().Distinct().Skip(pPageNo * pPageSize).Take(pPageSize).ToList();
            else
                return criteria.List<MachineType>().Distinct().ToList();
        }

        public int GetItemsCountBy(string pName, string pItemType)
        {
            var criteria = CurrentSession.CreateCriteria<MachineType>();
            criteria.CreateAlias("Synonyms", "SYN", NHibernate.SqlCommand.JoinType.LeftOuterJoin);
            criteria.Add(Expression.Eq("IsDeleted", false));

            if (pItemType != null && pItemType.Trim() != string.Empty)
                criteria.Add(Expression.Eq("Type", (MachineType)Enum.Parse(typeof(MachineType), pItemType)));

            if (pName != null && pName.Trim() != string.Empty)
            {
                pName = string.Format("%{0}%", pName);                
                criteria.Add(Expression.Or(Expression.InsensitiveLike("Name", pName), Expression.InsensitiveLike("SYN.Name", pName)));                
            }


            return criteria.List<MachineType>().Distinct().Count();
        }

        public IList<MachineType> GetConstituentsByParentID(Guid? pParentID, int pPageNo, int pPageSize)
        {
            MachineType parent = null;
                if (pParentID != null)
                    parent = CurrentSession.Get<MachineType>(pParentID);

                var criteria = CurrentSession.CreateCriteria<MachineType>();
                criteria.Add(Expression.Eq("IsDeleted", false));

                if (parent != null)
                    criteria.Add(Expression.Eq("Parent", parent));
                else
                    criteria.Add(Expression.Eq("Category", MachineCategory.SYSTEM));

                criteria.AddOrder(new Order("Name", true));

                return criteria.List<MachineType>().Skip(pPageNo * pPageSize).Take(pPageSize).ToList();            
        }

        public int GetConstituentsCountByParentID(Guid? pParentID)
        {
            MachineType parent = null;
            if (pParentID != null)
                parent = CurrentSession.Get<MachineType>(pParentID);

            var criteria = CurrentSession.CreateCriteria<MachineType>();
            criteria.Add(Expression.Eq("IsDeleted", false));

            if (parent != null)
                criteria.Add(Expression.Eq("Parent", parent));
            else
                criteria.Add(Expression.Eq("Category", MachineCategory.SYSTEM));

            return criteria.List().Count;
        }

        public void DeleteItems(string[] pItemIds, Guid pUserID)
        {
            List<Guid> idList = new List<Guid>();
            if (pItemIds.Count() > 0)
            {
                foreach (var p in pItemIds)
                {
                    if (p != null && p.Trim() != string.Empty)
                    {
                        idList.Add(Guid.Parse(p));
                    }
                }
            }

            var criteria = CurrentSession.CreateCriteria<MachineType>();
            criteria.Add(Expression.InG<Guid>("ID", idList));

            var list = criteria.List<MachineType>();
            list.AsParallel().ForAll(act => { act.IsDeleted = true; act.UpdatedBy = pUserID; CurrentSession.SaveOrUpdate(act); });        
        }

        #endregion

        #region Template Methods

        public Guid SaveTemplate(Template templateBizObject)
        {
            CurrentSession.SaveOrUpdate(templateBizObject);

            var criteria = CurrentSession.CreateCriteria<Template>();
            criteria.Add(Expression.Eq("Name", templateBizObject.Name));

            return criteria.UniqueResult<Template>().ID;
        }

        public IList<Template> GetTemplatesByName(string pName, int pPageNo, int pPageSize)
        {
            var criteria = CurrentSession.CreateCriteria<Template>();
            criteria.Add(Expression.Eq("IsDeleted", false));
            criteria.AddOrder(new Order("Name", true));

            if (pPageNo != -1)
                return criteria.List<Template>().Skip(pPageNo * pPageSize).Take(pPageSize).ToList();
            else
                return criteria.List<Template>();
        }

        public int GetTemplateCountByName(string pName)
        {
            var criteria = CurrentSession.CreateCriteria<Template>();
            criteria.Add(Expression.Eq("IsDeleted", false));
            criteria.AddOrder(new Order("Name", true));

            return criteria.List().Count;
        }

        public Template GetTemplateByID(Guid pID)
        {
            return CurrentSession.Get<Template>(pID);
        }

        public IList<MachineType> GetItemsByParentForTemplate(Guid? pParentID, Guid pTemplateID, int pPageNo, int pPageSize)
        {
            List<MachineType> machineItems = new List<MachineType>();

            var strTemplateID = pTemplateID.ToString();//BitConverter.ToString(pTemplateID.ToByteArray()).Replace("-", "");

            string sqlString = string.Empty;
            if (pParentID != null)
            {
                //C# GUID will not match with oracle GUID. So convert the C# GUID into Oracle GUID.
                var strParentID = pParentID.Value.ToString();//BitConverter.ToString(pParentID.Value.ToByteArray()).Replace("-", "");
                sqlString =
//                    string.Format(@"SELECT ID FROM MACHINE WHERE ID NOT IN (SELECT TM.MACHINEITEM_ID FROM TEMPLATE_MACHINERY TM 
//                        WHERE TM.TEMPLATE_ID = CAST('{0}' as uniqueidentifier)) AND PARENT_ID=CAST('{1}' as uniqueidentifier)"
//                    , strTemplateID, strParentID);
string.Format(@"SELECT ID FROM MACHINE_TYPE WHERE ID NOT IN (SELECT TM.MACHINEITEM_ID FROM TEMPLATE_MACHINERY TM 
                        WHERE TM.TEMPLATE_ID = '{0}') AND PARENT_ID='{1}'"
                    , strTemplateID, strParentID);
            }
            else
            {
                sqlString =
//                    string.Format(@"SELECT ID FROM MACHINE WHERE ID NOT IN (SELECT TM.MACHINEITEM_ID FROM TEMPLATE_MACHINERY TM 
//                        WHERE TM.TEMPLATE_ID =  CAST('{0}' as uniqueidentifier)) AND PARENT_ID IS NULL"
//                    , strTemplateID);
    string.Format(@"SELECT ID FROM MACHINE_TYPE WHERE ID NOT IN (SELECT TM.MACHINEITEM_ID FROM TEMPLATE_MACHINERY TM 
                        WHERE TM.TEMPLATE_ID =  '{0}') AND PARENT_ID IS NULL"
                    , strTemplateID);
            }
                       

            if (pPageSize != -1)
            {                
                var data = CurrentSession
                    .CreateSQLQuery(sqlString).List();

                foreach (var dataitem in data.Cast<Guid>().Skip(pPageNo * pPageSize).Take(pPageSize))
                {                    
                    //machineItems.Add(CurrentSession.Get<Item>(new Guid((byte[])dataitem)));
                    machineItems.Add(CurrentSession.Get<MachineType>(dataitem));
                }
            }
            else
            {
                var data = CurrentSession
                    .CreateSQLQuery(sqlString).List();

                foreach (var dataitem in data.Cast<object>().Skip(pPageNo * pPageSize).Take(pPageSize))
                {
                    machineItems.Add(CurrentSession.Get<MachineType>(dataitem));
                }
            }

            return machineItems;
        }

        public int GetItemsCountByParentForTemplate(Guid? pParentID, Guid pTemplateID)
        {
            var strTemplateID = pTemplateID.ToString();//BitConverter.ToString(pTemplateID.ToByteArray()).Replace("-", "");
            

            string sqlString = string.Empty;
            if (pParentID != null)
            {
                //C# GUID will not match with oracle GUID. So convert the C# GUID into Oracle GUID.
                //var strParentID = BitConverter.ToString(pParentID.Value.ToByteArray()).Replace("-", "");
                var strParentID = pParentID.Value.ToString();
                sqlString =
                    string.Format("SELECT * FROM MACHINE_TYPE WHERE ID NOT IN (SELECT TM.MACHINEITEM_ID FROM TEMPLATE_MACHINERY TM WHERE TM.TEMPLATE_ID = '{0}') AND PARENT_ID='{1}'"
                    , strTemplateID, pParentID);
            }
            else
            {
                sqlString =
                    string.Format("SELECT * FROM MACHINE_TYPE WHERE ID NOT IN (SELECT TM.MACHINEITEM_ID FROM TEMPLATE_MACHINERY TM WHERE TM.TEMPLATE_ID = '{0}') AND PARENT_ID IS NULL"
                    , strTemplateID);
            }

            return CurrentSession
                    .CreateSQLQuery(sqlString).List().Count;
        }

        public void RemoveTemplateItems(Guid pTemplateID, List<Guid> pItems)
        {
            var template = CurrentSession.Get<Template>(pTemplateID);           

            int idx = pItems.Count;
            while (idx > 0)
            {
                template.MachineItems.Remove(template.MachineItems.Where(e => e.ID == pItems[idx - 1]).Single());
                idx--;
            }

            CurrentSession.SaveOrUpdate(template);
            //NHybernate is simply removing the link between the parent and child. This followig line will delete all such things. 
            //CurrentSession.CreateSQLQuery("DELETE FROM TEMPLATE_MACHINERY WHERE TEMPLATE_ID IS NULL").ExecuteUpdate();
        }

        #endregion

        #region Vessel related methods

        public Vessel GetVesselByCode(Guid pVesselCode)
        {
            return CurrentSession.Get<Vessel>(pVesselCode);
        }

        public Guid SaveVessel(Vessel pVessel)
        {
            CurrentSession.SaveOrUpdate(pVessel);

            var criteria = CurrentSession.CreateCriteria<Vessel>();
            criteria.Add(Expression.Eq("Name", pVessel.Name));

            return criteria.UniqueResult<Vessel>().ID;
        }

        public IList<Vessel> GetVesselsByName(string pName, int pPageNo, int pPageSize)
        {
            var criteria = CurrentSession.CreateCriteria<Vessel>();
            if (pName != null && pName.Trim() != string.Empty)
                criteria.Add(Expression.InsensitiveLike("Name", pName));

            criteria.Add(Expression.Eq("IsDeleted", false));

            criteria.AddOrder(new Order("Name", true));           

            if (pPageSize == -1)
            {
                return criteria.List<Vessel>();
            }
            else
            {
                return criteria.List<Vessel>().Skip(pPageNo * pPageSize).Take(pPageSize).ToList();
            }
        }

        public IList<TemplateMachinery> GetTemplateMachineryByVesselCode(Guid pVesselCode)
        {
            IList<TemplateMachinery> mach = new List<TemplateMachinery>();

            var vsl = this.GetVesselByCode(pVesselCode);
            foreach (var item in vsl.SystemsTemplate.MachineItems)
            {
                mach.Add(item);
            }

            return mach;
        }

        public VesselMachine GetVesselItemByCode(Guid pVesselItemCode)
        {
            return CurrentSession.Get<VesselMachine>(pVesselItemCode);
        }

        public Guid CheckItemInVesselItem(Guid pVesselCode, Guid pItemCode)
        {
            var criteria = CurrentSession.CreateCriteria<Vessel>();
            var vslItems = CurrentSession.Get<Vessel>(pVesselCode).Items;
            if (vslItems.Where(exp => exp.ID == pItemCode).Count() > 0)
            {
                return vslItems.Where(exp => exp.ID == pItemCode).Single().ID;
            }
            else
            {
                return Guid.Empty;
            }
        }

        #endregion        

        #region SystemCode Related Methods

        public SystemCode GetSystemCodeByName(string pName)
        {
            var criteria = CurrentSession.CreateCriteria<SystemCode>();
            criteria.Add(Expression.Eq("Name", pName));
            criteria.Add(Expression.Eq("IsDeleted", false));

            return criteria.List<SystemCode>().Single(); ;
        }

        #endregion

        #region Vessel Jobs Related Methods

        public Job GetJobByCode(Guid pJobCode)
        {
            return CurrentSession.Get<Job>(pJobCode);
        }

        #endregion       
    }
}
